//
//  MEPrototype.m
//  MapEditor
//
//  Created by Eric on 3/3/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "MEPrototype.h"
#import "BBUtil.h"
#import "MEDefine.h"
#import "Box2D.h"
#import "GLES-Render.h"
#import "MEDefine.h"
#import "MEEditStageLayer.h"

@implementation MEPrototype
@synthesize className;
@synthesize sid;
@synthesize fileType;
@synthesize filePath;
@synthesize name;
@synthesize image;


@synthesize isBox2dObj;
@synthesize density;
@synthesize friction;
@synthesize restitution;
@synthesize bodyType;
@synthesize shapeIndex;
@synthesize shapes;
@synthesize shapeCenter;

@synthesize isSoftBody;
@synthesize segmentsNum;
@synthesize frequencyHzOut;
@synthesize dampingRatioOut;
@synthesize frequencyHzIn;
@synthesize dampingRatioIn;

@synthesize innerRateX;
@synthesize innerRateY;


-(void)dealloc{
    self.className = nil;
    self.filePath = nil;
    self.name = nil;
    self.image = nil;
    
    self.shapes = nil;
    [super dealloc];
}

+(id)prototype{
    MEPrototype* obj = [[[[self class] alloc] init] autorelease];
    obj.className = @"MESprite";
    return obj;
}


+(id)prototypeWithParam:(NSDictionary*)param{
    NSString* className = [param value:@"class" defaultVal:@"MESprite"];
    NSInteger sid = [param intValue:@"sid" defaultVal:0];
    NSInteger fileType = [param intValue:@"fileType" defaultVal:0];
    
    NSString* filePath = [param objectForKey:@"filePath"];
    NSImage *image = [[[NSImage alloc]initWithContentsOfFile:filePath] autorelease];   
    NSString* name = [param objectForKey:@"name"];

    BOOL isBox2dObj = [param boolValue:@"isBox2dObj" defaultVal:NO];
    CGFloat density = [param floatValue:@"density" defaultVal:DFT_BODY_DENSITY];
    CGFloat friction = [param floatValue:@"friction" defaultVal:DFT_BODY_FRICTION];
    CGFloat restitution = [param floatValue:@"restitution" defaultVal:DFT_BODY_RESTITUTION];
   
    
    NSInteger bodyType = [param intValue:@"bodyType" defaultVal:0];
    NSInteger shapeIndex = [param intValue:@"shapeIndex" defaultVal:0];
    
    BOOL isSoftBody = [param boolValue:@"isSoftBody" defaultVal:0];
    NSInteger segmentsNum = [param intValue:@"segmentsNum" defaultVal:DFT_SOFT_SEGMENT_NUM];
    CGFloat frequencyHzOut = [param floatValue:@"frequencyHzOut" defaultVal:DFT_SOFT_HZ_OUT];
    CGFloat dampingRatioOut = [param floatValue:@"dampingRatioOut" defaultVal:DFT_SOFT_DP_OUT];
    CGFloat frequencyHzIn = [param floatValue:@"frequencyHzIn" defaultVal:DFT_SOFT_HZ_IN];
    CGFloat dampingRatioIn = [param floatValue:@"dampingRatioIn" defaultVal:DFT_SOFT_DP_IN];
    
    CGFloat innerRateX = [param floatValue:@"innerRateX" defaultVal:DFT_SOFT_INNERRATEX];
    CGFloat innerRateY = [param floatValue:@"innerRateY" defaultVal:DFT_SOFT_INNERRATEY];
    
    
    MEPrototype* prototype = [[self class] prototype];
    prototype.className = className;
    prototype.sid = sid;
    prototype.fileType = fileType;
    prototype.filePath = filePath;
    prototype.image = image;
    prototype.name = name;
    prototype.isBox2dObj = isBox2dObj;
    prototype.density = density;
    prototype.friction = friction;
    prototype.restitution = restitution;
    prototype.bodyType = bodyType;
    prototype.shapeIndex = shapeIndex;
    prototype.isSoftBody = isSoftBody;
    prototype.segmentsNum = segmentsNum;
    prototype.frequencyHzOut = frequencyHzOut;
    prototype.dampingRatioOut = dampingRatioOut;
    prototype.frequencyHzIn = frequencyHzIn;
    prototype.dampingRatioIn = dampingRatioIn;
    prototype.innerRateX = innerRateX;
    prototype.innerRateY = innerRateY;
    
    NSArray* shapes = [param objectForKey:@"shapes"];
    if (shapes&&[shapes count]>0) {
        NSPoint shapeCenter = NSPointFromString([param objectForKey:@"shapeCenter"]);
        prototype.shapeCenter = NSPointToCGPoint(shapeCenter);
        
        NSMutableArray* customShapePointsTmp = [NSMutableArray arrayWithCapacity:[shapes count]];
        for (NSDictionary* cparam in shapes) {
            NSMutableDictionary* cparamTmp = [NSMutableDictionary dictionaryWithDictionary:cparam];
            
            NSArray* points = [cparam objectForKey:@"points"];
            NSMutableArray* pointsTmp = [NSMutableArray arrayWithCapacity:[points count]];
            for (NSString* ps in points) {
                NSPoint p = NSPointFromString(ps);
                NSValue* pv = [NSValue valueWithPoint:p];
                [pointsTmp addObject:pv];
            }
            
            [cparamTmp setObject:pointsTmp forKey:@"points"];
            [customShapePointsTmp addObject:cparamTmp];
        }
        prototype.shapes = customShapePointsTmp;
        
    }
    return prototype;
}



-(NSMutableDictionary*)toDict{
    NSString* pointFmt = @"@{x=%f;y=%f}";
    NSMutableDictionary* param = [NSMutableDictionary dictionaryWithCapacity:32];
    [param setObject:className forKey:@"class"];
    [param setObject:[NSNumber numberWithInteger:sid] forKey:@"sid"];
    [param setObject:[NSNumber numberWithInteger:fileType] forKey:@"fileType"];
    if (name) {
        [param setObject:name forKey:@"name"];
    }
    
    
    [param setObject:[NSNumber numberWithBool:isBox2dObj] forKey:@"isBox2dObj"];
    [param setObject:[NSNumber numberWithFloat:density] forKey:@"density"];
    [param setObject:[NSNumber numberWithFloat:friction] forKey:@"friction"];
    [param setObject:[NSNumber numberWithFloat:restitution] forKey:@"restitution"];
    
    
    [param setObject:[NSNumber numberWithInteger:bodyType] forKey:@"bodyType"];
    [param setObject:[NSNumber numberWithInteger:shapeIndex] forKey:@"shapeIndex"];
    [param setObject:[NSNumber numberWithBool:isSoftBody] forKey:@"isSoftBody"];
    [param setObject:[NSNumber numberWithInteger:segmentsNum] forKey:@"segmentsNum"];
    [param setObject:[NSNumber numberWithFloat:frequencyHzOut] forKey:@"frequencyHzOut"];
    [param setObject:[NSNumber numberWithFloat:dampingRatioOut] forKey:@"dampingRatioOut"];
    [param setObject:[NSNumber numberWithFloat:frequencyHzIn] forKey:@"frequencyHzIn"];
    [param setObject:[NSNumber numberWithFloat:dampingRatioIn] forKey:@"dampingRatioIn"];
    
    [param setObject:[NSNumber numberWithFloat:innerRateX] forKey:@"innerRateX"];
    [param setObject:[NSNumber numberWithFloat:innerRateY] forKey:@"innerRateY"];
    
    
    if (shapes&&[shapes count]>0) {
        NSPoint center = NSPointFromCGPoint(shapeCenter);
        NSString* centerStr = [NSString stringWithFormat:pointFmt, center.x, center.y];
        [param setObject:centerStr forKey:@"shapeCenter"];
        
        NSMutableArray* customShapePointsTmp = [NSMutableArray arrayWithCapacity:[shapes count]];
        for (NSDictionary* cparam in shapes) {
            NSMutableDictionary* cparamTmp = [NSMutableDictionary dictionaryWithDictionary:cparam];
            
            NSArray* points = [cparam objectForKey:@"points"];
            NSMutableArray* pointsTmp = [NSMutableArray arrayWithCapacity:[points count]];
            for (NSValue* pv in points) {
                NSPoint p = [pv pointValue];
                NSString* pointStr = [NSString stringWithFormat:pointFmt, p.x, p.y];
                [pointsTmp addObject:pointStr];
            }
            
            [cparamTmp setObject:pointsTmp forKey:@"points"];
            [customShapePointsTmp addObject:cparamTmp];
        }
        [param setObject:customShapePointsTmp forKey:@"shapes"];
    }
    
    if (filePath) {
        [param setObject:filePath forKey:@"filePath"];
    }
    return param;
}

-(NSString*)description{
    NSString* desc = [NSString stringWithFormat:@"%@:%d:%@",[super description], sid, name];
    return desc;
}

@end

@implementation MEPrototypeParam

@synthesize rotation;
@synthesize scale;
@synthesize pos;

@synthesize flipX;
@synthesize flipY;

+(id)prototypeParamWithDict:(NSDictionary*)param{
    MEPrototypeParam* spriteParam = [MEPrototypeParam prototypeWithParam:param];

    CGFloat rotation = [param floatValue:@"rotation" defaultVal:0];
    CGFloat scale = [param floatValue:@"scale" defaultVal:DFT_SPT_SCALE];
    CGPoint pos = NSPointToCGPoint(NSPointFromString([param value:@"pos" defaultVal:@"{x=0;y=0}"]));
    
    BOOL flipX = [param boolValue:@"flipX" defaultVal:NO];
    BOOL flipY = [param boolValue:@"flipY" defaultVal:NO];
    
    spriteParam.rotation = rotation;
    spriteParam.scale = scale;
    spriteParam.pos = pos;
    spriteParam.flipX = flipX;
    spriteParam.flipY = flipY;
    
    
    return spriteParam;
}
+(id)prototypeParamWithPrototype:(MEPrototype*)prototype{
    MEPrototypeParam* obj = [[[[self class] alloc] init] autorelease];
    obj.className = prototype.className;
    obj.sid = prototype.sid;
    obj.filePath = prototype.filePath;
    obj.image = prototype.image;
    obj.name = prototype.name;
    obj.scale = 1;
    obj.flipX = NO;
    obj.flipY = NO;
    obj.isBox2dObj = prototype.isBox2dObj;
    obj.density = prototype.density;
    obj.friction = prototype.friction;
    obj.restitution = prototype.restitution;
    obj.bodyType = prototype.bodyType;
    obj.shapeIndex = prototype.shapeIndex;
    obj.shapes = [NSMutableArray arrayWithArray:prototype.shapes];
    obj.shapeCenter = prototype.shapeCenter;
    obj.isSoftBody = prototype.isSoftBody;
    obj.segmentsNum = prototype.segmentsNum;
    obj.frequencyHzOut = prototype.frequencyHzOut;
    obj.dampingRatioOut = prototype.dampingRatioOut;
    obj.frequencyHzIn = prototype.frequencyHzIn;
    obj.dampingRatioIn = prototype.dampingRatioIn;
    obj.innerRateX = prototype.innerRateX;
    obj.innerRateY = prototype.innerRateY;
    return obj;
}

-(NSMutableDictionary*)toDict{
    NSMutableDictionary* param = [super toDict];
    
    NSString* pointFmt = @"@{x=%f;y=%f}";    
    [param setObject:[NSNumber numberWithFloat:rotation] forKey:@"rotation"];
    [param setObject:[NSNumber numberWithFloat:scale] forKey:@"scale"];
    [param setObject:[NSString stringWithFormat:pointFmt, pos.x, pos.y] forKey:@"pos"];
    [param setObject:[NSNumber numberWithFloat:flipX] forKey:@"flipX"];
    [param setObject:[NSNumber numberWithFloat:flipY] forKey:@"flipY"];
    return param;
}
@end


static MEPrototypeMgr* g_prototypeMgr;

@implementation MEPrototypeMgr
@synthesize prototypeDict;

-(void)dealloc{
    self.prototypeDict = nil;
    [super dealloc];
}
+(id)instance{
    if (!g_prototypeMgr) {
        g_prototypeMgr = [[MEPrototypeMgr alloc] init];
    }
    return g_prototypeMgr;
}
-(id)init{
    if (self=[super init]) {
        self.prototypeDict = [NSMutableDictionary dictionary];
    }
    return self;
}
-(id)createPrototype{
    MEPrototype* prototype = [MEPrototype prototype];
    prototype.sid = ++sidCount;
    prototype.isBox2dObj = NO;
    prototype.density = DFT_BODY_DENSITY;
    prototype.friction = DFT_BODY_FRICTION;
    prototype.restitution = DFT_BODY_RESTITUTION;
    prototype.isSoftBody = NO;
    prototype.segmentsNum = DFT_SOFT_SEGMENT_NUM;
    prototype.frequencyHzOut = DFT_SOFT_HZ_OUT;
    prototype.frequencyHzIn = DFT_SOFT_HZ_IN;
    prototype.dampingRatioOut = DFT_SOFT_DP_OUT;
    prototype.dampingRatioIn = DFT_SOFT_DP_IN;
    prototype.innerRateX = DFT_SOFT_INNERRATEX;
    prototype.innerRateY = DFT_SOFT_INNERRATEY;
    
    
    [prototypeDict setObject:prototype forKeyIN:prototype.sid];
    return prototype;
}

-(id)duplicate:(MEPrototype*)prototype{
    NSDictionary* param = [prototype toDict];
    MEPrototype* duplicate = [self dictToPrototype:param];
    duplicate.sid = ++ sidCount;
    NSImage *img = [[[NSImage alloc]initWithContentsOfFile:prototype.filePath] autorelease];
    duplicate.image = img;
    return duplicate;
}

-(id)dictToPrototype:(NSDictionary*)param{
    MEPrototype* prototype = [MEPrototype prototypeWithParam:param];
    [prototypeDict setObject:prototype forKeyIN:prototype.sid];
    sidCount = MAX(sidCount, prototype.sid + 1);
    return prototype;
}


-(void)removePrototype:(MEPrototype*)prototype{
    [prototypeDict removeObjectForKeyIN:prototype.sid];
}

-(void)removeAllPrototypes{
    [prototypeDict removeAllObjects];
}

-(id)prototypeWithSid:(NSInteger)sid{
    return [prototypeDict objectForKeyIN:sid];
}

@end